package com.itheima.app.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.autoconfig.face.AipFaceTemplate;
import com.itheima.autoconfig.im.HuanXinTemplate;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.autoconfig.sms.SmsTemplate;
import com.itheima.domain.db.Log;
import com.itheima.domain.db.User;
import com.itheima.domain.db.UserInfo;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.db.UserService;
import com.itheima.utils.ConstantUtil;
import com.itheima.utils.JwtUtil;
import com.itheima.vo.ErrorResult;
import com.itheima.vo.UserInfoVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.time.Duration;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Component //加入springmvc容器
public class UserManager {

    @DubboReference
    UserService userService;

    @Autowired
    SmsTemplate smsTemplate;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @DubboReference
    UserInfoService userInfoService;

    @Autowired
    AipFaceTemplate aipFaceTemplate;

    @Autowired
    OssTemplate ossTemplate;

    @Autowired
    HuanXinTemplate huanXinTemplate;

    @Autowired
    RabbitTemplate rabbitTemplate;


    //保存用户
    public Long save(User user){
        Long id = userService.save(user);
        return id;
    }

    //根据手机查询用户
    public User findByMobile(String mobile){
        User user = userService.findByMobile(mobile);
        return user;
    }

    //发送验证码
    public void sendCode(String phone) {
        //1.生成随机验证码
        String code = RandomUtil.randomNumbers(6);

        // TODO 项目方便,以后项目上线了,删除
        code = "123456";

        //2.调用阿里云模板发送短信
        // TODO 以后项目上线了,开启注释
        //smsTemplate.sendSms(phone,code);

        //3.将验证码保存到redis中,时效5分钟  //  sms:13600136000 = 123456
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE + phone,code, Duration.ofMinutes(5));
    }

    //注册和登录
    public ResponseEntity regAndLogin(Map<String, String> map) {
        //1.获取手机号和验证码
        String phone = map.get("phone");
        String verificationCode = map.get("verificationCode");

        //2.判断验证码和redis中是否相同,若不同返回错误提示
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        String redisCode = operations.get(ConstantUtil.SMS_CODE + phone);

        //使用hutools
        if(!StrUtil.equals(verificationCode,redisCode)){
            //return ResponseEntity.status(500).body("你输入的验证码有误!");
            return ResponseEntity.status(500).body(ErrorResult.loginError());//在domain实体类
        }

        //3.远程调用service,查询手机号判断用户是否存在
        User user = userService.findByMobile(phone);

        boolean isNew;

        //3.1若存在,则isNew=false
        if(user != null){
            isNew = false;
        }else{
            //3.2若不存在,则isNew=true,封装user数据,保存到数据库中
            isNew = true;

            user = new User();
            user.setMobile(phone);
            user.setPassword(ConstantUtil.INIT_PASSWORD);

            Long userId = userService.save(user);

            //别忘记给用户设置id
            user.setId(userId);

            //向环信注册用户
            huanXinTemplate.register("HX"+userId);
        }

        //4.准备用户数据(id,手机号),生成token
        Map<String,Object> userMap = new HashMap<>();
        userMap.put("id",user.getId());
        userMap.put("mobile",user.getMobile());

        String token = JwtUtil.createToken(userMap);

        //5.以后用户每次请求过来的时候都需要解析token,获取用户信息,有点麻烦,为了减少麻烦,
        // token作为key,user的json字符串作为value存入redis中,设置时效30天
        //operations.set("token"+token, JSON.toJSONString(user),Duration.ofDays(30));
        operations.set(ConstantUtil.USER_TOKEN+token, JSON.toJSONString(user),Duration.ofDays(30));

        //6.准备返回的数据(map),且返回
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);

        //7.可以不写,建议把验证码删除一下
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE+phone);

        //8.封装log对象,向mq发送日志对象
        Log log = new Log();
        log.setUserId(user.getId());
        log.setLogTime(DateUtil.formatDate(new Date()));
        log.setPlace("闽商国贸");
        log.setEquipment("iphone13");
        log.setType(isNew?"0102":"0101");

        rabbitTemplate.convertAndSend("tanhua.log",log);


        return ResponseEntity.ok(resultMap);
    }

    //完善用户信息
    public ResponseEntity saveUserInfo(UserInfo userInfo, String token) {
        //1.从token中获取用户
        //User user = getUserFromToken(token);

        //1.1 判断用户是否为空,若为空,返回401
        /*if (user == null) {
            return ResponseEntity.status(401).body(null);
        }*/

        //1.从token中获取用户(有统一token类了)
        User user = UserHolder.get();

        //2.给userInfo设置用户id
        userInfo.setId(user.getId());

        //3.远程调用service完成保存操作
        userInfoService.save(userInfo);

        return ResponseEntity.ok(null);
    }

    //从token中获取用户信息
    public User getUserFromToken(String token) {
        //token不为空
        if (StrUtil.isNotBlank(token)) {
            String userJson = stringRedisTemplate.opsForValue().get(ConstantUtil.USER_TOKEN + token);
            //Json不为空
            if (StrUtil.isNotBlank(userJson)) {
                return JSON.parseObject(userJson, User.class);
            }
        }
        return null;
    }

    //补充头像
    public ResponseEntity saveUserInfoHead(MultipartFile headPhoto, String token) throws IOException {
        //1.通过token获取用户
        User user = UserHolder.get();

        //2.判断头像是否为人脸,若不是返回错误
        if (!aipFaceTemplate.detect(headPhoto.getBytes())) {
            return ResponseEntity.status(500).body(ErrorResult.faceError());
        }

        //3.是头像,将用户头像保存到oss上,返回url
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //4.创建一个UserInfo,设置id和头像
        UserInfo userInfo = new UserInfo();
        userInfo.setId(user.getId());
        userInfo.setAvatar(url); //头像
        userInfo.setCoverPic(url); //封面

        //5.远程调用service完成更新操作
        userInfoService.update(userInfo);

        return ResponseEntity.ok(null);
    }


    public ResponseEntity findUserInfoById(Long id) {
        //1.远程调用service查询userInfo
        UserInfo userInfo = userInfoService.findByUserId(id);

        //2.创建userInfoVo对象
        UserInfoVo vo = new UserInfoVo();

        //3.属性拷贝(htool工具类,参数一:有数据对象,参数2:目标对象)
        BeanUtil.copyProperties(userInfo,vo);

        //4.返回userInfoVo
        return ResponseEntity.ok(vo);
    }


    public ResponseEntity updateUserInfo(UserInfo userInfo, String token) {
        //1.通过token获取用户
        User user = UserHolder.get();

        //2.若用户存在,给userInfo去设置id
        userInfo.setId(user.getId());

        //3.远程调用service完成更新操作
        userInfoService.update(userInfo);

        return ResponseEntity.ok(null);
    }


    /*
    2222222222222222222222222222222222
     */

    //保存用户
    /*public Long save(User user){
        Long id = userService.save(user);
        return id;
    }*/

    //根据手机查询用户
    /*public User findByMobile(String mobile){
        User user = userService.findByMobile(mobile);

        return user;
    }*/

    //发送验证码
    /*public void sendCode(String phone){
        //1.生成随机验证码
        String code = RandomUtil.randomNumbers(6);

        code = "123456";

        //2.调用阿里云模板发送短信
        //  以后项目上线了,开启注释
        //smsTemplate.sendSms(phone,code);

        //3.将验证码保存到redis中,时效5分钟  //  sms:13600136000 = 123456
        stringRedisTemplate.opsForValue().set(ConstantUtil.SMS_CODE+phone,code,Duration.ofMinutes(5));

    }*/

    //注册和登录
    /* public ResponseEntity regAndLogin2(Map<String, String> map) {
        //1.获取手机号和验证码
        String phone = map.get("phone");
        String verificationCode = map.get("verificationCode");

        //2.判断验证码和redis中是否相同,若不同返回错误提示
        String redisCode = stringRedisTemplate.opsForValue().get(ConstantUtil.SMS_CODE + phone);
        //使用hutools
        if (!StrUtil.equals(verificationCode,redisCode)) {
            //return ResponseEntity.status(500).body("你输入的验证码有误!");
            return ResponseEntity.status(500).body(ErrorResult.loginError());
        }

        //3.远程调用service,查询手机号判断用户是否存在
        User user = userService.findByMobile(phone);

        boolean isNew;

        //3.1若存在,则isNew=false
        if(user != null){
            isNew = false;
        }else{
            //3.2若不存在,则isNew=true,封装user数据,保存到数据库中
            isNew = true;

            user = new User();
            user.setMobile(phone);
            user.setPassword(ConstantUtil.INIT_PASSWORD);

            Long userId = userService.save(user);

            //别忘记给用户设置id
            user.setId(userId);

            //向环信注册用户
            huanXinTemplate.register("HX"+userId);
        }

        //4.准备用户数据(id,手机号),生成token
        Map<String,Object> userMap = new HashMap<>();
        userMap.put("id",user.getId());
        userMap.put("mobile",user.getMobile());

        String token = JwtUtil.createToken(userMap);

        //5.以后用户每次请求过来的时候都需要解析token,获取用户信息,有点麻烦,为了减少麻烦,
        // token作为key,user的json字符串作为value存入redis中,设置时效30天
        //operations.set("token"+token, JSON.toJSONString(user),Duration.ofDays(30));
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        operations.set(ConstantUtil.USER_TOKEN+token, JSON.toJSONString(user),Duration.ofDays(30));

        //6.准备返回的数据(map),且返回
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);

        //7.可以不写,建议把验证码删除一下
        stringRedisTemplate.delete(ConstantUtil.SMS_CODE+phone);

        return ResponseEntity.ok(resultMap);
    }*/

}
